package io.gitee.cengxiaoxiao.wrapper;

import cn.idev.excel.FastExcelFactory;
import cn.idev.excel.converters.localdate.LocalDateStringConverter;
import cn.idev.excel.converters.localdatetime.LocalDateTimeStringConverter;
import cn.idev.excel.util.StringUtils;
import cn.idev.excel.write.builder.ExcelWriterBuilder;
import io.gitee.cengxiaoxiao.converters.LocalTimeConverter;
import io.gitee.cengxiaoxiao.exceptions.ExcelException;
import io.gitee.cengxiaoxiao.tools.ExcelUtil;

import java.io.*;
import java.nio.charset.StandardCharsets;
import java.util.Collection;

/**
 * Excel写入封装类
 * 包装了FastExcel的写入方法，并注册了自定义转换器
 */
public class ExcelWriteWrapper {

    private static final ExcelWriterBuilder BaseBuilder =
            FastExcelFactory.write()
                    .charset(StandardCharsets.UTF_8)
                    .autoCloseStream(true)
                    .registerConverter(LocalTimeConverter.INSTANCE())
                    .registerConverter(new LocalDateStringConverter())
                    .registerConverter(new LocalDateTimeStringConverter());

    /**
     * 写入Excel到字节数组
     *
     * @param head 表头
     * @param data 数据
     * @param <S>  数据类型
     * @return 字节数组
     */
    public static <S> byte[] writeBytes(Class<S> head, Collection<S> data) {
        return writeStream(head, data).toByteArray();
    }

    /**
     * 写入Excel到字节数组输出流
     *
     * @param head 表头
     * @param data 数据
     * @param <S>  数据类型
     * @return 字节数组输出流
     */
    public static <S> ByteArrayOutputStream writeStream(Class<S> head, Collection<S> data) {
        if (head == null) {
            throw new IllegalArgumentException("head不能为空");
        }
        if (data == null || data.isEmpty()) {
            throw new IllegalArgumentException("数据不能为空");
        }
        ByteArrayOutputStream bos = new ByteArrayOutputStream();
        BaseBuilder.file(bos)
                .head(head)
                .sheet()
                .doWrite(data);
        return bos;
    }

    /**
     * 写入Excel到指定文件
     *
     * @param file 输出文件
     * @param head 表头
     * @param data 数据
     * @param <S>  数据类型
     */
    public static <S> void write(File file,
                                 Class<S> head,
                                 Collection<S> data) {
        if (file == null) {
            throw new IllegalArgumentException("file不能为空");
        }
        try (FileOutputStream fos = new FileOutputStream(file)) {
            write(fos, head, data);
        } catch (IOException e) {
            throw new ExcelException("写入Excel失败", e);
        }
    }

    /**
     * 写入Excel到指定路径
     *
     * @param outputPath 输出路径
     * @param head       表头
     * @param data       数据
     * @param <S>        数据类型
     */
    public static <S> void write(String outputPath,
                                 Class<S> head,
                                 Collection<S> data) {
        if (StringUtils.isBlank(outputPath)) {
            throw new IllegalArgumentException("outputPath不能为空");
        }
        ExcelUtil.isExcel(outputPath);
        write(new File(outputPath), head, data);
    }


    public static <S> void write(OutputStream os,
                                 Class<S> head,
                                 Collection<S> data) {
        write(os, head, 0, data);
    }

    /**
     * 写入Excel
     *
     * @param os      输出流
     * @param head    表头
     * @param sheetNo 工作表序号
     * @param data    数据
     * @param <S>     数据类型
     */
    public static <S> void write(OutputStream os,
                                 Class<S> head,
                                 int sheetNo,
                                 Collection<S> data) {
        if (os == null) {
            throw new IllegalArgumentException("OutputStream不能为空");
        }
        if (sheetNo < 0) {
            sheetNo = 0;
        }
        if (head == null) {
            throw new IllegalArgumentException("head不能为空");
        }
        if (data == null || data.isEmpty()) {
            throw new IllegalArgumentException("写入数据不能为空");
        }
        // 转换字典数据
        data.forEach(ExcelUtil::dictConvert);
        // 导出Excel
        BaseBuilder.file(os)
                .head(head)
                .sheet(sheetNo)
                .doWrite(data);
    }
}
